#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

#include "shmfifo.h"
#include "shmstruct.h"
#include "dataxchgtable.h"

void * __l0032_shm_initialize(const char* shmname, size_t sz, int iscreated);
int __l0032_lock_initialize(void *mutexlock_addr);
void __l0032_ipc_mutex_lock(pthread_mutex_t *lock);
void __l0032_ipc_mutex_unlock(pthread_mutex_t *lock);


void l0032_shmstruct_lock(struct l0032_shmstruct* shmstruct)
{
	__l0032_ipc_mutex_lock(&shmstruct->lock);
}

void l0032_shmstruct_unlock(struct l0032_shmstruct* shmstruct)
{
	__l0032_ipc_mutex_unlock(&shmstruct->lock);
}

struct l0032_shmstruct* l0032_shmstruct_open(const char* shmname, size_t sz, int bCreate)
{	
	struct l0032_shmstruct* shmstruct = NULL;
	//int iscreated = 0;

	if (shmname && strlen(shmname) < L0032_SHM_FILENAME_MAX && sz != 0) {
		sz = L0032_PAGEALIGN(sz);

		shmstruct = __l0032_shm_initialize(shmname, sz, bCreate);
		if (shmstruct && bCreate) {
			shmstruct->sz = sz;
			if (__l0032_lock_initialize(&shmstruct->lock) == -1) {
				printf("Fail to initialize mutex lock for metadata in dxtable\n");
				goto err2;
			}
		}
		//printf("shmstruct addr:%x, sz:%d-%0x \n", shmstruct, sz, sz);
	}
	else if (shmname == NULL) {
		printf("Shm name is NULL\n");
		goto err1;
	}
	else if (strlen(shmname) >= L0032_SHM_FILENAME_MAX) {
		//printf("Shm name is length is too big(%ld)\n\n", strlen(shmname));
		goto err1;
	}
	else if (sz == 0) {
		//printf("Invalid size(%ld) for shm\n", sz);
		goto err1;
	}
	//printf("l0032_shmstruct_open shmstruct->sz:%ld \n", shmstruct->sz);
	
	return shmstruct;

err2:
	munmap(shmstruct, shmstruct->sz);
err1:
	return NULL;
}

void *l0032_shmstruct_getshm(struct l0032_shmstruct* shmstruct)
{
	return shmstruct->mem;
}

void l0032_shmstruct_close(struct l0032_shmstruct* shmstruct)
{
	if (shmstruct) {
		munmap(shmstruct, shmstruct->sz);
	}
}


